package cn.tedu.rewrite;

import org.junit.Test;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Arrays;

/**
 * @author :Colin
 * @version 创建时间: 2021/6/25 10:20
 */
public class TestReflect {

    @Test
    public void Test1() throws Exception {
        Class<?> st = Student.class;
        Class<?> clazz = Class.forName("cn.tedu.rewrite.Student");
        Method[] ms = clazz.getMethods();
        for(Method m:ms){
            System.out.println(m.getName());
            Class<?>[] pt = m.getParameterTypes();
            System.out.println(Arrays.toString(pt));

        }
    }
    @Test
    public void getFields() throws Exception {
        Class<?> clazz = Class.forName("cn.tedu.rewrite.Student");
        /*注意！目前成员变量的修饰符必须是public才能获取
        采用默认的修饰符反射获取不到
         */
        Field[] fs =clazz.getFields();
        for(Field f:fs){
            System.out.println(f.getName());
            System.out.println(f.getType().getName());
        }

    }
    /*方式一：通过字节码对象直接调用newInstance（） 方法，触发无参构造来创建对象*/
    /*方式2：先获取指定的构造函数，再通过这个构造函数对象来创建对象*/
    @Test
    public void getObject() throws Exception {
        //
        Class<?> clazz = new Student().getClass();
        Object o =  clazz.newInstance();//Student{name='null', age=0}
        /*会触发无参构造*/
        System.out.println("方式2");
        //指定用哪个构造方法调用对象
        /*注意！这个方法参数类型是构造方法参数类型的字节码对象*/
        Constructor<?> c = clazz.getConstructor(String.class, int.class);
        Object o2 = c.newInstance("asd", 3);
        System.out.println(o2);
        //通过反射创建出来的对象获取属性值并使用方法
        /*
        此处需要把父类型object的o2，强制转换为子类型Student的s
        为什么要强制转换,因为我们想要使用子类的特有功能，而父类不能使用子类特有功能
        Object父类中是没有Student子类自己的属性和功能
        所以，我们把之前的父类行的子类对象转回成子类型，去调用子类的特有功能。
        这个现象称作：向下造型【注意向下之前必须先向上造型，纯纯的父类对象不能向下造型】
         */
        Student s=(Student) o2;
        System.out.println(s.name);
        System.out.println(s.age);
        System.out.println(s.play(3));




    }

}
